/*
    Copyright (c) 2008-2009, Prashanta Shrestha All Rights Reserved.
    Available under GNU Lesser General Public License >= 3.0 as published by the Free Software Foundation.
    see <http://www.gnu.org/licenses/>
*/
/*-------------------------------------------------------------------------------------
  CLASS : qDojo.core.AjaxHandler
  ====================================================================================
  - Who implements(/derives from) this class?
  	-----------------------------------------
  	Any entity that needs to make a AJAX call.
  	View widget classes that display information gathered from server. The including class should have its own
  	"render(response)" function, this is for the case when response is meant for view widget, which is itself or its 
  	children widget classes. 
  ------------------------------------------------------------------------------------------------------------------	  
  - Coordinates Requests transfer to server and handle Responses from server
  - Handles showing/hiding of 'loading... ' dialog
  	Uses the global progress dialog - "_gpd". 
    If "_gpd" not present create and append to window.body .
    Hence all classes using this class will use the common global progress dialog, assuming that there is only one
    active (view widget) class sending request to server that NEED TO MASK entire viewport.   
  - All request MUST contain the key - 'eid' whose value is the event name to which the server responses. This is the
  	event name with which Controller maps to appropriate event handler class method.  	 
  - Types of requests 
  	[1] Request with URL containing manually assigned key-value pairs (AJAX)
  	[2] Request with data from form (AJAX)
  	[3] Request with file(s) to upload and optinally including data from a form.(uses dojo.io.iFrame and two forms)  	  		
  	(NO error handling logic for requests below .....)
  	[4] Request for file to download (and send form data along with request if applicable)
  	     (Note: file download using <iframe> tag, name-value-pair -> "fe=1" is added to req. to indicate a Requesting-A-File event) 	  
  - dojo.xhrGet supports UTF-8 encoding by default, so no need to mention explicitly
  - BUT, dojo.io.iframe DOES NOT do any kind of encoding and so far not needed since only used to request files from server.   
   ------------------------------------------------------------------------------------------------------------------    
  - Types of response (All responses are treated as JSON except file download and preformatted HTML content):
  GLOBAL -   
  	1. Data to be displayed on DIALOG -- try to replace global dialog by App.Specific Dialog Widgets   	
  	2. Data to be displayed on TOASTER
  	3. JAVASCRIPT code snippet or function name to invoke - useful when invoking events programmatically (or just about any JS code) 	
  	4. URL to which the browser need to be REDIRECTED    
  VIEW CONTEXT -	
	5. Data to render on  VIEW WIDGET - most commonly used (a general purpose stuff).
  	(All above response are handled by "handleResponse")  	
  - Response can contain data for multiple views. Eg. for a general view and a dialog...    
  - Response structure:	
  	response = { eid	: "event_id_request" , 				 
				 target : [ { _rpt:"d" 	, payload: {title:"dialog_title" , html : "content of dialog" , href: "url of page to load in dialog"} },				 			
				 			{ _rpt:"t"	, payload: {msgType:0/1/2 , html : "content of toaster"  } },
				 			{ _rpt:"js" , payload: {method:"script_to_execute" } },
				 			{ _rpt:"vw" , payload : { viewWidget specific data in JSON format / or just about anything }				 										 											 						   
				 			{ _rpt:"w"  , payload: {url:"url to which to direct the browser" }};				 							 				 			
				 		  ]  
  			   }	   
  [for further detail refer to documentation]
  -------------------------------------------------------------------------------------*/  
  
dojo.provide("qDojo.core.AjaxHandler");

dojo.require("qDojo.dijix.LoadingDialog");
dojo.require("qDojo.dijix.Dialog");
dojo.require("qDojo.dijix.Toaster");
dojo.require("dojo.io.iframe");
dojo.require("dijit.Dialog");

dojo.declare("qDojo.core.AjaxHandler", null , {

		// Global UIs (only for reference)
		gt	: "_gt" ,	// Global Toaster
		gd	: "_gd" ,	// Global Dialog	
		gld	: "_gld",	// Global Loading Dialog - never destroyed during lifetime of application	
		
		timeout	: 15000	, // Ajax request timeout in micro-seconds
		
		// ===========================================================
		// Class Constructor
		// -----------------------------------------------------------
		constructor: function()
		{					
			// check if global loading dialog is preset
			if( (dijit.byId("_gld") == null) || ( typeof dijit.byId("_gld") == "undefined") )
			{
				var dialog = new qDojo.dijix.LoadingDialog( {id:"_gld"} );  		
				dojo.body().appendChild(dialog.domNode);         	
			}
			// may need to check for global dialog too ?			
		},
		// ===========================================================
		// Create Global Download iFrame
		// -----------------------------------------------------------
		createGDIF: function()
		{
			if( (dojo.byId("_gdif") == null) || ( typeof dijit.byId("_gdif") == "undefined") ){	       	
	       		var node = document.createElement("iframe");
	       		node.id = "_gdif";
	       		node.style.cssText= "position:absolute;width:100px;height:10px;bottom:0px;left:0px;background:red;zIndex:100;visibility:hidden";	       		
	       		dojo.body().appendChild(node);
	       	}
	    },
		// ===========================================================
		// Show Loading Dialog
		// -----------------------------------------------------------
		showLoading: function()
		{
	    	if( !dijit.byId("_gld").shown )	dijit.byId("_gld").show();
	    },	    
		// ===========================================================
		// Hide Loading Dialog
	    // -----------------------------------------------------------
	    hideLoading: function()
	    {
	    	if( dijit.byId("_gld").shown )	dijit.byId("_gld").hide();
	    },
	    // ===========================================================
		// Toast some info on the toaster
		// -----------------------------------------------------------
        toast: function(payload)
        {
        	if(dijit.byId("_gt") == null )
		   	     this.gt = new qDojo.dijix.Toaster( {id: "_gt" } );
		   	this.gt.show(payload.type,payload.message,payload.title);  			
        },
        // ===========================================================
		// Put some info on global dialog
		// -----------------------------------------------------------
        showDialog: function( payload )
        {             
        	var dialog = ( (dojo.byId("_gd") == null) || ( typeof dijit.byId("_gd") == "undefined") )? new dijit.Dialog( {id:"_gd" } ) : dijit.byId("_gd");			   
			if( (payload.html == null) || (typeof payload.html == "undefined"))	
			     dialog.setHref(payload.href);
			else
			     dialog.attr("content",payload.html);	
			dialog.titleNode.innerHTML = payload.title;
			dialog.show();	
			dialog.style.zIndex = 1000;
        },
        // ===========================================================
		// [1] Dispatch simple event request (simplest one)
		//  dispatch( {eid:"asdf",a:32,b:12} )
        // -----------------------------------------------------------
        exec: function(request , handleAs , silent)
        {
        	if(typeof request == "object")
            {   if(request.eid)
                    request = dojo.objectToQuery(request);
                 else{
                    console.error("No eid found in : " + dojo.toJson(request));
                    return;
                 }                                                                                 
            }else
                request = "eid=" + ((typeof request == "undefined" || request=="")? "nullRequest":request);
            if(!silent) this.showLoading();
            dojo.xhrGet( 
            {
                _this   : this , 
                url     : "go?"+request+"&_rt=0" ,
                handleAs: "text", 
                load    : function(response , ioArgs) { this._this.handleResponse(response,handleAs); },
                error   : function(err , ioArgs){this._this.handleError(err,ioArgs);},                                          
                timeout : this.timeout 
            });
        },
        // ===========================================================
		// [2] Dispatch with data from a form 
		// -----------------------------------------------------------
		execForm : function( request , formId , handleAs ,silent)
		{
		    if(typeof request == "object")
            {   if(request.eid)
                    request = dojo.objectToQuery(request);
                 else{
                    console.error("No eid found in : " + dojo.toJson(request));
                    return;
                 }                                                                                 
            }else
                request = "eid=" + ((typeof request == "undefined" || request=="")? "nullRequest":request);                
			if(!silent)	this.showLoading();			
			dojo.xhrGet( {
				_this 	: this , 
		 		url 	: "go?"+request+"&_rt=0" ,
		 		form 	: formId ,
		 		handleAs: "text" , 		 		
		 		load    : function(response , ioArgs) { this._this.handleResponse(response,handleAs); },
                error   : function(err , ioArgs){this._this.handleError(err,ioArgs);},
		 		timeout	: this.timeout 		 		
	 		});	
		},
		// ===========================================================
		// [3] Dispatch form data with file(s) 
        // -----------------------------------------------------------
		dispatchFormWithFile: function(event , dataForm , fileForm , silent)
		{		    
			if(!silent)	this.showLoading();							
			var q = dojo.formToQuery(dataForm); // this does URI encoding by default											
			dojo.io.iframe.send(
			{
				_this 	: this,
				form	: fileForm,//dojo.byId(fileForm),
				handleAs: "text",
				url 	: "go?eid="+event+"&"+q+"&if=1" ,
				handle	: function(response, ioArgs){
								if(response instanceof Error){	this._this.hideLoading();	this._this.handleError(response,ioArgs,1);	}
								else	this._this.handleResponse(response);														
							}
			});			
		},
		// ===========================================================
		// [3] Dispatch form data with file(s)
        // -----------------------------------------------------------
		dispatchMultiPartForm: function(event , formName , silent)
		{		    
			if(!silent)	this.showLoading();				
			dojo.io.iframe.send({
				_this 	: this,
				form	: formName,
				handleAs: "text",
				url 	: "go?eid="+event+"&if=1" ,				
				handle	: function(response, ioArgs){
								if(response instanceof Error){	this._this.hideLoading();	this._this.handleError(response,ioArgs,1);	}
								else	this._this.handleResponse(response);														
						  }
			});			
		},				  
        // ===========================================================
		// [4] Get file for specified event (and send form data with req.)
        // -----------------------------------------------------------
        getFile: function(event , formId)
        {   
        	var query = formId? dojo.formToQuery(formId) : "";
        	var url = "go?eid="+event+"&fe=1&"+query;
        	this.createGDIF();
	       	dojo.byId("_gdif").src = url;       		
        },
		// ===========================================================
		// Send response to response handler
        // -----------------------------------------------------------
        handleResponse: function(response,handleAs)
        {	  
        	this.hideLoading();
	        console.log(response);
	        if(handleAs == "html")
                this.renderView(response,null);
			else
	        {
				var r = dojo.fromJson(response);															   		
		   		for(var i=0;i < r.target.length ; i++ )
		   		{
	                if(r.target[i]._rpt == "dialog")	
		   				 this.showDialog( r.target[i].payload );		   									
		   			else if(r.target[i]._rpt == "toaster")
		   			     this.toast(r.target[i].payload);
		   			else if(r.target[i]._rpt == "js") 
		   			     eval(r.target[i].payload.method);		
		   			else if(r.target[i]._rpt == "redirect")	
		   			     window.location.href =r.target[i].payload.url;	
		   			else if(r.target[i]._rpt == "viewPanel" || r.target[i]._rpt == "print")	
		   			     this.renderView(r.target[i].payload , r.event  , r.target[i]._rpt);		   			      		   				
		   		}		   				
			   	this.customHandleResponse(r);			   	
			 }			 
        },        
        // ===========================================================
		// May need to do something after response is handled before 
		// returning from the AJAX loop
		// -----------------------------------------------------------
        customHandleResponse: function(response)
        {
            // power to the people	
        },       
        // ===========================================================
		// Render View - override this by the view that implements this AjaxHandler
		// -----------------------------------------------------------
        renderView: function(content,event)
        {	  
	        console.warn("Gatta render this response: " + content);
        },        
        // ===========================================================
		// AJAX Request Error Handler
		// -----------------------------------------------------------
        handleError: function(err,ioArgs)
        {	this._this.hideLoading() ;
            msg = err + "; Error Type: " + ( err.dojoType == 200 ? "unknown/js error" : err.dojoType);
            showDialog({html: msg , title:"Error"});					
        },
        // ===========================================================
		// HTTP Status Code 
		// -----------------------------------------------------------
        code2ErrorMsg: function(val)
        {
        	switch(val){
        		case 200: return "HTTP request successful";case 301: return "Moved permanently";case 403: return "Forbidden";case 400: return "Bad Request";
        		case 404: return "Not Found";case 414: return "Request-URI Too Long";case 500: return "Internal Server Error";case 502: return "Bad Gateway";default : return "Unknown code";
        	}
        }        
});